package edu.njfu.service.impl;

import edu.njfu.mapper.BookStockMapper;
import edu.njfu.mapper.BorrowerMapper;
import edu.njfu.mapper.BorrowingMapper;
import edu.njfu.pojo.BookStock;
import edu.njfu.pojo.Borrower;
import edu.njfu.pojo.Borrowing;
import edu.njfu.service.IBorrowingService;
import edu.njfu.util.AdminException;
import edu.njfu.util.MyDateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
@Transactional
public class BorrowingServiceImpl implements IBorrowingService {
    @Autowired
    private BorrowingMapper borrowingMapper;
    @Autowired
    private BorrowerMapper borrowerMapper;
    @Autowired
    private BookStockMapper bookStockMapper;

    @Override
    public List<Borrowing> findAll() {
        // 判断归还状态
        List<Borrowing> borrowings = borrowingMapper.findAll();
        for (Borrowing borrowing : borrowings) {
            // 如果状态已丢失、归还、超时归还 不更新
            if (borrowing.getStatus() == Borrowing.STATUS_LOST || borrowing.getStatus() == Borrowing.STATUS_RETURNED
                    || borrowing.getStatus() == Borrowing.STATUS_OVERTIME_RETURNED) {
                continue;
            }
            // 超时借阅
            if (borrowing.getReturnTime() == null) {
                // 获取借阅时间
                Date borrowTime = borrowing.getBorrowTime();
                // 获取当前时间
                Date date = new Date();
                Long day = MyDateUtil.timeResult(borrowTime, date);
                if (day > Borrowing.BORROWING_LONGEST_TIME) {
                    borrowing.setStatus(Borrowing.STATUS_OVERTIME_BORROWING);
                }
                borrowingMapper.updateByPrimaryKeySelective(borrowing);
            }
        }
        return borrowings;
    }

    @Override
    public List<Borrowing> findByStatus(Integer status) {
        return borrowingMapper.findByStatus(status);
    }

    @Override
    public void save(String borrowerName, String borrowingName) {
        Borrowing borrowing = new Borrowing();
        // 判断借阅人是否存在
        List<Borrower> borrowers = borrowerMapper.findAll();
        for (Borrower borrower : borrowers) {
            if (borrowerName.equals(borrower.getName())) {
                Long borrowerId = borrower.getId();
                borrowing.setBorrowerId(borrowerId);
                borrowing.setBorrower(borrower);
            }
        }
        // 判断书是否存在（通过判断库存）
        List<BookStock> bookStocks = bookStockMapper.findAll();
        for (BookStock bookStock : bookStocks) {
            if (bookStock.getBook().getName().equals(borrowingName)) {
                if (bookStock.getStock() == 0) {
                    throw new AdminException("操作失败, 该书库存不足");
                }
                // 借出去之后库存 -1
                bookStock.setStock(bookStock.getStock() - 1);
                bookStockMapper.updateByPrimaryKey(bookStock);

                borrowing.setBookId(bookStock.getBook().getId());
                borrowing.setBook(bookStock.getBook());
            }
        }
        if (borrowing.getBorrowerId() == null || borrowing.getBookId() == null) {
            throw new AdminException("操作失败, 请核对信息是否正确");
        }
        // 初始状态为 0（借阅中）
        borrowing.setStatus((short) 0);
        borrowingMapper.insertSelective(borrowing);
    }

    @Override
    public void returnBook(Long id) {
        Borrowing borrowing = borrowingMapper.selectByPrimaryKey(id);
        // 获取当前归还时间
        Date date = new Date();
        // 获取借阅时长判断归还状态
        borrowing.setReturnTime(date);
        Long timeResult = MyDateUtil.timeResult(borrowing.getBorrowTime(), date);
        // 超时归还
        if (timeResult > Borrowing.BORROWING_LONGEST_TIME) {
            borrowing.setStatus(Borrowing.STATUS_OVERTIME_RETURNED);
        } else {
            borrowing.setStatus(Borrowing.STATUS_RETURNED);
        }
        List<BookStock> bookStocks = bookStockMapper.findAll();
        // 还书之后 库存 + 1
        for (BookStock bookStock : bookStocks) {
            if (borrowing.getBookId().equals(bookStock.getBookId())) {
                bookStock.setStock(bookStock.getStock() + 1);
                bookStockMapper.updateByPrimaryKey(bookStock);
            }
        }
        borrowingMapper.updateByPrimaryKey(borrowing);
    }

    @Override
    public void lostBook(Long id) {
        Borrowing borrowing = borrowingMapper.selectByPrimaryKey(id);
        // 检查借阅状态
        Short status = borrowing.getStatus();
        if (status != Borrowing.STATUS_BORROWING && status != Borrowing.STATUS_OVERTIME_BORROWING) {
            throw new AdminException("操作失败, 该记录不在借阅状态中, 无法报失");
        }
        // 检查总库存
        BookStock bs = bookStockMapper.selectByBookId(borrowing.getBookId());
        if (bs.getTotalStock() <= 0) {
            throw new AdminException("操作失败, 此书籍总库存已经为零, 请与库存管理员核对信息");
        }

        // 修改借阅状态
        borrowing.setStatus(Borrowing.STATUS_LOST);
        borrowingMapper.updateByPrimaryKeySelective(borrowing);
        // 修改总库存 -1
        bs.setTotalStock(bs.getTotalStock() - 1);
        bookStockMapper.updateByPrimaryKeySelective(bs);
    }

    @Override
    public Map<String, List> findHotBook() {
        Map<String, List> map = new HashMap<>();
        List<Map<String, Object>> hotBooks = borrowingMapper.findHotBook();
        List<Object> bookNames = new ArrayList<>();
        for (Map<String, Object> hotBook : hotBooks) {
            bookNames.add(hotBook.get("name"));
        }
        map.put("bookNames", bookNames);
        map.put("bookDatas", hotBooks);
        return map;
    }

    @Override
    public Map<String, List> mostBorrower() {
        Map<String, List> result = new HashMap<>();
        String firstDay = MyDateUtil.getCurrentMonthFirstDay();
        List<Map<String, Object>> map = borrowingMapper.findBorrowCountAfterDate(firstDay);

        List<Object> borrowerNames = new ArrayList<>();
        List<Object> borrowCounts = new ArrayList<>();
        for (Map<String, Object> obj : map) {
            borrowerNames.add(obj.get("borrowerName"));
            borrowCounts.add(obj.get("borrowCount"));
        }
        result.put("borrowerNames", borrowerNames);
        result.put("borrowCounts", borrowCounts);
        return result;
    }
}
